package com.cowin.inf.service.impl;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cowin.base.exception.ServiceException;
import com.cowin.base.result.Result;
import com.cowin.base.result.ResultGenerator;
import com.cowin.inf.controller.EmosController;
import com.cowin.inf.model.KyBdcRouteLog;
import com.cowin.inf.model.KyBdcRouteSetting;
import com.cowin.inf.model.KyVehicleQueue;
import com.cowin.inf.model.RouteModule;
import com.cowin.inf.model.vo.BaseRouteModule;
import com.cowin.inf.model.vo.InOutBoundVo;
import com.cowin.inf.model.vo.KyVehicleQueueVo;
import com.cowin.inf.service.*;
import com.cowin.sys.model.TmVhcVehicle;
import com.cowin.sys.service.TmBasVehiclequeueService;
import com.cowin.sys.service.TmVhcVehicleService;
import com.google.common.collect.ImmutableMap;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * Copyright (C), 1998-2018, 奇瑞信息
 *
 * @author : 于超
 * @Date: 2019/9/3 8:59
 * @Description:
 */
@Slf4j
@Service
@Transactional(rollbackFor = RuntimeException.class)
public class BdcRouteServiceImpl implements BdcRouteService {

    public static final String P13 = "P13";
    public static final String P14 = "P14";
    public static final String P12 = "P12";
    public static final String K13 = "K13";
    public static final String K2 = "K2";
    public static final String W2 = "W2";
    public static final String K11 = "K11";
    public static final String K12 = "K12";
    public static final String P10 = "P10";
    public static final String P11 = "P11";
    public static final String P200 = "P200";
    public static final String MESSAGE = "message";

    private final Map<String, String> queueTypeMap = ImmutableMap.of("K2", "K2", "K11", "K2", "P1", "P1", "P10", "P1");

    @Resource
    private KyBdcRouteSettingService kyBdcRouteSettingService;

    @Resource
    private KyBdcRouteLogService kyBdcRouteLogService;

    @Resource
    private TmVhcVehicleService tmVhcVehicleService;

    @Resource
    private TmBasVehiclequeueService tmBasVehiclequeueService;

    @Resource
    private KyBdcVehicleService kyBdcVehicleService;

    @Resource
    private KyVehicleQueueService kyVehicleQueueService;
    @Resource
    private EmosController emosController;


    @Value("${interface.uri.mes.pointRecordUrl}")
    private String pointRecordUrl;


    @Override
    public Result getRouter(RouteModule routeModule) {
        log.info("路由点接口=={}", JSON.toJSONString(routeModule));
        String routerPoint = routeModule.getMesScanNo().trim();
        log.info("查询路由决策");
        KyBdcRouteSetting kyBdcRouteSetting = kyBdcRouteSettingService.findByRoutePoint(routerPoint);
        log.info("查询路由决策结束");
        KyBdcRouteLog kyBdcRouteLog = new KyBdcRouteLog();
        if (kyBdcRouteSetting == null) {
            log.info("------路由决策未配置------");
            return ResultGenerator.genFailResult("路由决策未配置");
        } else {
            String decisionNode = "";
            Short bdcMode = kyBdcRouteSetting.getBdcMode();
            if (1 == bdcMode) {
                log.info("手动模式1===路径{}", kyBdcRouteSetting.getDecisionNode1());
                decisionNode = kyBdcRouteSetting.getDecisionNode1();
                remove(routeModule, decisionNode);
            } else if (2 == bdcMode) {
                log.info("手动模式2===路径{}", kyBdcRouteSetting.getDecisionNode2());
                decisionNode = kyBdcRouteSetting.getDecisionNode2();
                remove(routeModule, decisionNode);
            } else {
                String queueType = queueTypeMap.get(routerPoint);
                //查询是不是优先队列   优先对列 在队列那么排队  如果不在锁定队列 可以直接入库
                log.info("查询是不是优先队列");
                Integer countByVin = tmBasVehiclequeueService.findCountByVin(routeModule.getVin().trim());
                log.info("查询是不是优先队列结束=={}", countByVin);
                //获取队列第一个
                log.info("查询队列第一个");
                KyVehicleQueue queueFirst = kyVehicleQueueService.findQueueFirst(queueType, routerPoint);
//                log.info("查询队列第一个结束=={}", queueFirst.getVin());
                if (countByVin >= 1) {
                    //优先队列
                    if (queueFirst == null) {
                        //是优先队列 并且锁定队列为空
                        decisionNode = kyBdcRouteSetting.getDecisionNode1();
                        remove(routeModule, decisionNode);
                    } else {
                        if (queueFirst.getVin().equals(routeModule.getVin())) {
                            //是优先队列 并且是锁定队列第一个
                            decisionNode = kyBdcRouteSetting.getDecisionNode1();
                            remove(routeModule, decisionNode);
                        } else {
                            //是否已在锁定对列
                            log.info("是否已在锁定对列");
                            KyVehicleQueueVo isInQueue = kyVehicleQueueService.findIsInQueue(queueType, routeModule.getVin());
                            log.info("是否已在锁定对列结束");
                            if (isInQueue != null) {
                                //是优先对列 但是已在锁定队列
                                decisionNode = kyBdcRouteSetting.getDecisionNode2();
                            } else {
                                //是优先对列 不在锁定队列 不入库 放行
                                decisionNode = kyBdcRouteSetting.getDecisionNode1();
                                remove(routeModule, decisionNode);
                            }
                        }
                    }
                } else {
                    if (queueFirst == null) {
                        //锁定对列为空  全部入库
                        decisionNode = kyBdcRouteSetting.getDecisionNode2();
                    } else if (routeModule.getVin().equals(queueFirst.getVin())) {
                        log.info("是队列第一个");
                        //是队列第一个 自动路由
                        decisionNode = kyBdcRouteSetting.getDecisionNode1();
                        log.info("remove====ing");
                        remove(routeModule, decisionNode);
                    } else if (!routeModule.getVin().equals(queueFirst.getVin())) {
                        //不是队列第一个
                        decisionNode = kyBdcRouteSetting.getDecisionNode2();
                    }
                }
            }
            //入涂装 插入涂装数据库
            if (K11.equals(routerPoint) && K12.equals(decisionNode)) {
                log.info("异步入涂装 插入涂装数据库");
                CompletableFuture.runAsync(() -> {
                    try {
                        emosController.insert(routeModule.getVin().trim());
                    } catch (Exception e2) {
                        log.error(e2.getMessage());
                    }
                });
            }
            kyBdcRouteLog.setDeparture(routerPoint);
            kyBdcRouteLog.setVin(routeModule.getVin());
            kyBdcRouteLog.setCreateTime(new Date());
            kyBdcRouteLog.setDestination(decisionNode);
            kyBdcRouteLogService.save(kyBdcRouteLog);
            BaseRouteModule baseRouteModule = new BaseRouteModule();
            baseRouteModule.setDecisionNode(decisionNode);
            baseRouteModule.setVin(routeModule.getVin());
            kyBdcVehicleService.vehiclePointRecord(routeModule.getVin(), routeModule.getMesScanNo(), decisionNode);
            return ResultGenerator.genSuccessResult(baseRouteModule);
        }
    }

    /**
     * 功能描述: <br>
     *
     * @param
     * @return:
     * @since: 1.0.0
     * @Author:yuchao
     * @Date: 2020/3/13 10:33
     */
    private void remove(RouteModule routeModule, String decisionNode) {
        log.info("remove===开始");
        String routerPoint = routeModule.getMesScanNo().trim();
        String queueType = queueTypeMap.get(routerPoint);
        if (queueType != null) {
            if (K11.equals(routerPoint) && K12.equals(decisionNode)) {
                log.info("kyVehicleQueueService.remove K2");
                kyVehicleQueueService.remove(queueType, routeModule.getVin());
                log.info("kyVehicleQueueService.remove K2 end");
            } else if (P10.equals(routerPoint) && P11.equals(decisionNode)) {
                log.info("kyVehicleQueueService.remove P1");
                kyVehicleQueueService.remove(queueType, routeModule.getVin());
                log.info("kyVehicleQueueService.remove P1 end");
            }
        }
    }


    @Override
    public Result pointRecord(RouteModule pointRecord) {
        log.info("过点记录{}", JSON.toJSONString(pointRecord));
        KyBdcRouteLog kyBdcRouteLog = new KyBdcRouteLog();
        kyBdcRouteLog.setDeparture(pointRecord.getMesScanNo());
        kyBdcRouteLog.setVin(pointRecord.getVin());
        kyBdcRouteLog.setCreateTime(new Date());
        int save = kyBdcRouteLogService.save(kyBdcRouteLog);
        log.info(" 记录{}条过点记录到数据库", save);
        kyBdcVehicleService.vehiclePointRecord(pointRecord.getVin(), pointRecord.getMesScanNo(), "");
        //W2升级为焊装20点 发送MES过点记录
        if (W2.equals(pointRecord.getMesScanNo())) {
            pointRecord.setMesScanNo("FN220");
            String returnData = HttpUtil.post(pointRecordUrl, JSON.toJSONString(pointRecord));
            Map returnMap;
            try {
                log.info("焊装20点异步入涂装 插入涂装数据库");
                CompletableFuture.runAsync(() -> {
                    try {
                        emosController.insert(pointRecord.getVin().trim());
                    } catch (Exception e2) {
                        log.error(e2.getMessage());
                    }
                });
                log.info("焊装20点发送过点记录===={}", pointRecord.getVin());
                returnMap = JSON.parseObject(JSONObject.parseObject(returnData).toString(), Map.class);
            } catch (Exception e) {
                //格式转化失败
                return ResultGenerator.genFailResult(e.getMessage());
            }
            log.info("焊装20点过点记录接口调用返回 {}", returnData);
            if ("".equals(returnMap.get(MESSAGE))) {
                return ResultGenerator.genSuccessResult();
            } else {
                return ResultGenerator.genFailResult(returnMap.get(MESSAGE).toString());
            }
        } else if (P11.equals(pointRecord.getMesScanNo())) {
            //发送过点记录到MES
            log.info("发送 P11 过点记录到MES");
            String returnData = HttpUtil.post(pointRecordUrl, JSON.toJSONString(pointRecord));
            log.info("发送过点记录到MES 结束");
            Map returnMap;
            try {
                log.info("发送P11过点记录===={}", pointRecord.getVin());
                returnMap = JSON.parseObject(JSONObject.parseObject(returnData).toString(), Map.class);
            } catch (Exception e) {
                //格式转化失败
                throw new ServiceException(e.getMessage());
            }
            log.info("P11过点记录接口调用返回 {}", returnData);
            if ("".equals(returnMap.get(MESSAGE))) {
                return ResultGenerator.genSuccessResult();
            } else {
                return ResultGenerator.genFailResult(returnMap.get(MESSAGE).toString());
            }
        }
        return ResultGenerator.genSuccessResult(pointRecord);
    }

    @Override
    public Result inOutBound(RouteModule inOutBound) {
        log.info("出入库记录{}", JSON.toJSONString(inOutBound));
        InOutBoundVo inOutBoundVo = new InOutBoundVo();
        TmVhcVehicle byVinNo = tmVhcVehicleService.findByVinNo(inOutBound.getVin().trim());
        String psOrWsBody = tmVhcVehicleService.isPsOrWsBody(inOutBound.getVin().trim());
        inOutBoundVo.setIsPsOrWs(psOrWsBody);
        if (byVinNo != null) {
            String vehicleStatus = byVinNo.getVehicleStatus();
            log.info("MES系统车辆SET-IN-OUT状态 {}", vehicleStatus);
            String mesScanNo = inOutBound.getMesScanNo();
            // in:0  out:1
            if (P13.equals(mesScanNo) || P14.equals(mesScanNo)) {
                //（白车身/油漆过）可以进出车不带雪橇，MES系统先做SetIN/OUT，车到位时，MES告知BDC允许出BDC或不允许出BDC必须回BDC。
                inOutBoundVo.setIsPermit(vehicleStatus.equals(inOutBound.getInOut()));
                return ResultGenerator.genSuccessResult(inOutBoundVo);
            } else if (P12.equals(mesScanNo) || K13.equals(mesScanNo)) {
                //K13（白车身）P12（油漆过车身）可以进出车带雪橇。从K13 P12 出BDC，需要再MES系统先做SetOUT操作，当车到位BDC调MES的Webservice，MES告知BDC允许出BDC或不允许出BDC必须回BDC。从K13 P12回BDC不需要MES系统做SetIN操作。
                if ("0".equals(inOutBound.getInOut())) {
                    inOutBoundVo.setIsPermit(Boolean.TRUE);
                    return ResultGenerator.genSuccessResult(inOutBoundVo);
                } else {
                    inOutBoundVo.setIsPermit(vehicleStatus.equals(inOutBound.getInOut()));
                    return ResultGenerator.genSuccessResult(inOutBoundVo);
                }
            }
        }
        return ResultGenerator.genFailResult("MES系统" + inOutBound.getVin() + "车辆无信息");
    }


}
